package com.sfdk.graphics.engine.utils
{
import flash.display.BitmapData;
import flash.geom.Matrix;
import flash.geom.Point;
import flash.geom.Rectangle;

public class ExtendedBitmapData
	{
		private var topLeft_ : BitmapData;
		private var topRight_ : BitmapData;
		private var bottomLeft_ : BitmapData;
		private var bottomRight_ : BitmapData;
		
		private var maxTile_ : int = 3360;
		private var TILE_SIZE : int;
		
		private var hasRightPart : Boolean;
		private var hasBottomPart : Boolean;
		public function ExtendedBitmapData(mapWidth : int , mapHeight : int , transparent : Boolean , defaultColor : uint, tileSize : int) : void
		{
			TILE_SIZE = tileSize;
			
			if(mapWidth > maxTile_)
			{
				hasRightPart = true;
				if(mapWidth > (2 * maxTile_))
					throw(new Error("Trop long !"));
			}
			if(mapHeight > maxTile_)
				hasBottomPart = true;
			
			if(hasRightPart && hasBottomPart)
			{ 
				topLeft_ = new BitmapData(maxTile_, maxTile_, transparent, defaultColor);
				topRight_ = new BitmapData(mapWidth - maxTile_, maxTile_, transparent, defaultColor);
				bottomLeft_ = new BitmapData(maxTile_, mapHeight - maxTile_, transparent, defaultColor);
				bottomRight_ = new BitmapData(mapWidth - maxTile_, mapHeight - maxTile_, transparent, defaultColor);
			}
			else if(hasRightPart)
			{
				topLeft_ = new BitmapData(maxTile_, mapHeight, transparent, defaultColor);
				topRight_ = new BitmapData(mapWidth - maxTile_, mapHeight, transparent, defaultColor);
				bottomLeft_ = null;
				bottomRight_ = null;
			}
			else if(hasBottomPart)
			{
				topLeft_ = new BitmapData(mapWidth, maxTile_, transparent, defaultColor);
				topRight_ = null;
				bottomLeft_ = new BitmapData(mapWidth, mapHeight - maxTile_, transparent, defaultColor);
				bottomRight_ = null;
			}			
			else
			{
				topLeft_ = new BitmapData(mapWidth, mapHeight, transparent, defaultColor);
				topRight_ = null;
				bottomLeft_ = null;
				bottomRight_ = null;
			}
		}
		
		public function clear(defaultColor : uint = 0) : void
		{
			var fillRect : Rectangle = new Rectangle();
			if(topLeft_ != null)
			{
				fillRect.width = topLeft_.width;
				fillRect.height = topLeft_.height;
				topLeft_.fillRect(fillRect, defaultColor);
			}
			
			if(topRight_ != null)
			{
				fillRect.width = topRight_.width;
				fillRect.height = topRight_.height;
				topRight_.fillRect(fillRect, defaultColor);
			}
			
			if(bottomLeft_ != null)
			{
				fillRect.width = bottomLeft_.width;
				fillRect.height = bottomLeft_.height;
				bottomLeft_.fillRect(fillRect, defaultColor);	
			}
				
			if(bottomRight_ != null)
			{
				fillRect.width = bottomRight_.width;
				fillRect.height = bottomRight_.height;
				bottomRight_.fillRect(fillRect, defaultColor);
			}
		}
		
		public function copyPixels(sourceBitmapData : BitmapData, sourceRect : Rectangle, destPoint : Point, alphaBitmapData : BitmapData = null, alphaPoint : Point = null, merge : Boolean = false) : void
		{
			var startInLeft : Boolean;
			var startInTop : Boolean;
			var endInLeft : Boolean;
			var endInTop : Boolean;
			_sourceRect.x = sourceRect.x;
			_sourceRect.y = sourceRect.y;
			_sourceRect.width = sourceRect.width;
			_sourceRect.height = sourceRect.height;
			_sourcePoint.x = destPoint.x;
			_sourcePoint.y = destPoint.y;
			var diffStartX : int = _sourcePoint.x - maxTile_;
			var diffStartY : int = _sourcePoint.y - maxTile_;
			var diffX : int = (_sourcePoint.x + _sourceRect.width) - maxTile_;
			var diffY : int = (_sourcePoint.y + _sourceRect.height) - maxTile_;
			if(diffStartX < 0)
			{
				startInLeft = true;
				endInLeft = diffX <= 0;
			}
			else
			{
				startInLeft = false;
				endInLeft = false;
			}
			
			if(diffStartY < 0)
			{
				startInTop = true;
				endInTop = diffY <= 0;
			}
			else
			{
				startInTop = false;
				endInTop = false;
			}
			
			if(startInLeft && endInLeft)
			{ // Tout à gauche
				if(startInTop && endInTop)
				{ // Tout en haut
					topLeft_.copyPixels(sourceBitmapData, _sourceRect, _sourcePoint, alphaBitmapData, alphaPoint, merge);
				}
				else if(startInTop && !endInTop)
				{ // Un bout en haut et un en bas
					topLeft_.copyPixels(sourceBitmapData, _sourceRect, _sourcePoint, alphaBitmapData, alphaPoint, merge);
					_sourcePoint.y = diffStartY;
					bottomLeft_.copyPixels(sourceBitmapData, _sourceRect, _sourcePoint, alphaBitmapData, alphaPoint, merge);
				}
				else
				{ // Tout à bas
					_sourcePoint.y -= maxTile_;
					bottomLeft_.copyPixels(sourceBitmapData, _sourceRect, _sourcePoint, alphaBitmapData, alphaPoint, merge);
				}
			}
			else if(startInLeft && !endInLeft)
			{ // Un bout à gauche un bout à droite
				if(startInTop && endInTop)
				{ // Tout en haut split en 2
					topLeft_.copyPixels(sourceBitmapData, _sourceRect, _sourcePoint, alphaBitmapData, alphaPoint, merge);
					_sourcePoint.x = diffStartX;
					topRight_.copyPixels(sourceBitmapData, _sourceRect, _sourcePoint, alphaBitmapData, alphaPoint, merge);
				}
				else if(startInTop && !endInTop)
				{ // Un bout en haut et un en bas split en 4
					topLeft_.copyPixels(sourceBitmapData, _sourceRect, _sourcePoint, alphaBitmapData, alphaPoint, merge);
					_sourcePoint.y -= maxTile_;
					
					bottomLeft_.copyPixels(sourceBitmapData, _sourceRect, _sourcePoint, alphaBitmapData, alphaPoint, merge);
					_sourcePoint.y += maxTile_;
					
					_sourcePoint.x = diffStartX;
					topRight_.copyPixels(sourceBitmapData, _sourceRect, _sourcePoint, alphaBitmapData, alphaPoint, merge);
					
					_sourcePoint.y -= maxTile_;
					bottomRight_.copyPixels(sourceBitmapData, _sourceRect, _sourcePoint, alphaBitmapData, alphaPoint, merge);
				}
				else
				{ // Tout en bas split en 2
					_sourcePoint.y -= maxTile_;
					bottomLeft_.copyPixels(sourceBitmapData, _sourceRect, _sourcePoint, alphaBitmapData, alphaPoint, merge);
					_sourcePoint.x = diffStartX;
					bottomRight_.copyPixels(sourceBitmapData, _sourceRect, _sourcePoint, alphaBitmapData, alphaPoint, merge);

				}
			}
			else
			{ // Tout à droite
				_sourcePoint.x -= maxTile_;
				if(startInTop && endInTop)
				{ // Tout en haut
					topRight_.copyPixels(sourceBitmapData, _sourceRect, _sourcePoint, alphaBitmapData, alphaPoint, merge);
				}
				else if(startInTop && !endInTop)
				{ // Un bout en haut et un en bas split en 2
					topRight_.copyPixels(sourceBitmapData, _sourceRect, _sourcePoint, alphaBitmapData, alphaPoint, merge);
					_sourcePoint.y = diffStartY;
					bottomRight_.copyPixels(sourceBitmapData, _sourceRect, _sourcePoint, alphaBitmapData, alphaPoint, merge);
				}
				else
				{ // Tout à bas
					_sourcePoint.y -= maxTile_;
					bottomRight_.copyPixels(sourceBitmapData, _sourceRect, _sourcePoint, alphaBitmapData, alphaPoint, merge);
				}
			}
		}
		
		private var _sourceRect : Rectangle = new Rectangle();
		private var _sourcePoint : Point = new Point();
		
		public function copyPixelsTo(destBitmapData : BitmapData, sourceRect : Rectangle, destPoint : Point, alphaBitmapData : BitmapData = null, alphaPoint : Point = null, merge : Boolean = false) : void
		{
			var startInLeft : Boolean;
			var startInTop : Boolean;
			var endInLeft : Boolean;
			var endInTop : Boolean;
			_sourceRect.x = sourceRect.x;
			_sourceRect.y = sourceRect.y;
			_sourceRect.width = sourceRect.width;
			_sourceRect.height = sourceRect.height;
			_sourcePoint.x = destPoint.x;
			_sourcePoint.y = destPoint.y;
			if(sourceRect.x < maxTile_)
			{
				startInLeft = true;
				endInLeft = (sourceRect.x + sourceRect.width) <= maxTile_;
			}
			else
			{
				startInLeft = false;
				endInLeft = false;
			}
			
			if(sourceRect.y < maxTile_)
			{
				startInTop = true;
				endInTop = (sourceRect.y + sourceRect.height) <= maxTile_;
			}
			else
			{
				startInTop = false;
				endInTop = false;
			}
			if(startInLeft && endInLeft)
			{ // Tout à gauche
				if(startInTop && endInTop)
				{ // Tout en haut
					destBitmapData.copyPixels(topLeft_ , sourceRect, _sourcePoint, alphaBitmapData, alphaPoint, merge);
				}
				else if(startInTop && !endInTop)
				{ // Un bout en haut et un en bas
					_sourceRect.x = sourceRect.x;
					_sourceRect.y = sourceRect.y;
					_sourceRect.width = sourceRect.width;
					_sourceRect.height = maxTile_ - sourceRect.y;
					destBitmapData.copyPixels(topLeft_, _sourceRect, _sourcePoint, alphaBitmapData, alphaPoint, merge);
					
					_sourceRect.y = 0;
					_sourcePoint.y += maxTile_ - sourceRect.y;
					_sourceRect.height = sourceRect.height - _sourceRect.height; 
					if(bottomLeft_)
						destBitmapData.copyPixels(bottomLeft_, _sourceRect, _sourcePoint, alphaBitmapData, alphaPoint, merge);
				}
				else if(bottomLeft_)
				{ // Tout à bas
					_sourceRect.y -= maxTile_;
					destBitmapData.copyPixels(bottomLeft_ , _sourceRect, _sourcePoint, alphaBitmapData, alphaPoint, merge);
				}
			}
			else if(startInLeft && !endInLeft)
			{ // Un bout à gauche un bout à droite
				if(startInTop && endInTop)
				{ // Tout en haut
					_sourceRect.x = sourceRect.x;
					_sourceRect.y = sourceRect.y;
					_sourceRect.width = maxTile_ - sourceRect.x;
					_sourceRect.height = sourceRect.height;
					destBitmapData.copyPixels(topLeft_, _sourceRect, _sourcePoint, alphaBitmapData, alphaPoint, merge);
					
					_sourceRect.x = 0;
					_sourcePoint.x += _sourceRect.width;
					_sourceRect.width = sourceRect.width - _sourceRect.width; 
					if(topRight_)
						destBitmapData.copyPixels(topRight_, _sourceRect, _sourcePoint, alphaBitmapData, alphaPoint, merge);
				}
				else if(startInTop && !endInTop)
				{ // Un bout en haut et un en bas
					_sourceRect.x = sourceRect.x;
					_sourceRect.y = sourceRect.y;
					_sourceRect.width = maxTile_ - sourceRect.x;
					_sourceRect.height = maxTile_ - sourceRect.y;
					destBitmapData.copyPixels(topLeft_, _sourceRect, _sourcePoint, alphaBitmapData, alphaPoint, merge);
					
					_sourceRect.x = 0;
					_sourcePoint.x += _sourceRect.width;
					_sourceRect.width = sourceRect.width - _sourceRect.width;
					if(topRight_)
						destBitmapData.copyPixels(topRight_, _sourceRect, _sourcePoint, alphaBitmapData, alphaPoint, merge);
					
					_sourceRect.x = sourceRect.x;
					_sourceRect.y = 0;
					_sourcePoint.x = destPoint.x;
					_sourcePoint.y += _sourceRect.height;
					_sourceRect.width = maxTile_ - sourceRect.x;
					_sourceRect.height = sourceRect.height - _sourceRect.height;
					if(bottomLeft_)
						destBitmapData.copyPixels(bottomLeft_, _sourceRect, _sourcePoint, alphaBitmapData, alphaPoint, merge);
					
					_sourceRect.x = 0;
					_sourcePoint.x += _sourceRect.width;
					_sourceRect.width = sourceRect.width - _sourceRect.width; 
					if(bottomRight_)
						destBitmapData.copyPixels(bottomRight_, _sourceRect, _sourcePoint, alphaBitmapData, alphaPoint, merge);
				}
				else
				{ // Tout à bas
					_sourceRect.x = sourceRect.x;
					_sourceRect.y = sourceRect.y - maxTile_;
					_sourceRect.width = maxTile_ - sourceRect.x;
					_sourceRect.height = sourceRect.height;
					if(bottomLeft_)
						destBitmapData.copyPixels(bottomLeft_, _sourceRect, _sourcePoint, alphaBitmapData, alphaPoint, merge);
					
					_sourceRect.x = 0;
					_sourcePoint.x += _sourceRect.width;
					_sourceRect.width = sourceRect.width - _sourceRect.width; 
					if(bottomRight_)
						destBitmapData.copyPixels(bottomRight_, _sourceRect, _sourcePoint, alphaBitmapData, alphaPoint, merge);
				}
			}
			else
			{ // Tout à droite
				_sourceRect.x -= maxTile_;
				if(startInTop && endInTop)
				{ // Tout en haut
					if(topRight_)
						destBitmapData.copyPixels(topRight_, _sourceRect, _sourcePoint, alphaBitmapData, alphaPoint, merge);
				}
				else if(startInTop && !endInTop)
				{ // Un bout en haut et un en bas
					_sourceRect.x = sourceRect.x - maxTile_;
					_sourceRect.y = sourceRect.y;
					_sourceRect.width = sourceRect.width;
					_sourceRect.height = maxTile_ - sourceRect.y;
					destBitmapData.copyPixels(topRight_, _sourceRect, _sourcePoint, alphaBitmapData, alphaPoint, merge);
					
					_sourceRect.y = 0;
					_sourcePoint.y += _sourceRect.height;
					_sourceRect.height = sourceRect.height - _sourceRect.height; 
					if(bottomRight_)
						destBitmapData.copyPixels(bottomRight_, _sourceRect, _sourcePoint, alphaBitmapData, alphaPoint, merge);
				}
				else if(bottomRight_)
				{ // Tout à bas
					_sourceRect.y -= maxTile_;
					destBitmapData.copyPixels(bottomRight_ , _sourceRect, _sourcePoint, alphaBitmapData, alphaPoint, merge);
				}
			}
		}
		
		
		public function getThumbnail(isSol : Boolean = false) : BitmapData
		{
			var color : uint = 0;
			if(isSol)
				color = 0xFFFFFFFF;
			var smallTopLeft : BitmapData = new BitmapData(maxTile_ / TILE_SIZE, maxTile_ / TILE_SIZE, true, color);
			var smallTopRight : BitmapData;
			var smallBottomLeft : BitmapData;
			var smallBottomRight : BitmapData;
			
			var thumbnailWidth : int = maxTile_ / TILE_SIZE;
			var thumbnailHeight : int = maxTile_ / TILE_SIZE;
			var thumbnailData : BitmapData;
			var scaleMatrix : Matrix = new Matrix();
			scaleMatrix.scale(1 / TILE_SIZE, 1 / TILE_SIZE);
			smallTopLeft.draw(topLeft_, scaleMatrix);
			
			if(topRight_ != null)
			{
				thumbnailWidth += topRight_.width / TILE_SIZE;
				smallTopRight = new BitmapData(topRight_.width / TILE_SIZE, topRight_.height / TILE_SIZE, true, color);
				smallTopRight.draw(topRight_, scaleMatrix);
			}
			
			if(bottomLeft_ != null)
			{
				thumbnailHeight += bottomLeft_.height / TILE_SIZE;
				smallBottomLeft = new BitmapData(bottomLeft_.width / TILE_SIZE, bottomLeft_.height / TILE_SIZE, true, color);
				smallBottomLeft.draw(bottomLeft_, scaleMatrix);
			}
			
			if(bottomRight_ != null)
			{
				smallBottomRight = new BitmapData(bottomRight_.width / TILE_SIZE, bottomRight_.height / TILE_SIZE, true, color);
				smallBottomRight.draw(bottomRight_, scaleMatrix);
			}
			
			var sourceRect : Rectangle = new Rectangle(0,0, smallTopLeft.width, smallTopLeft.height);
			var destPoint : Point = new Point();
			
			thumbnailData = new BitmapData(thumbnailWidth, thumbnailHeight, true, color);
			thumbnailData.copyPixels(smallTopLeft, sourceRect, destPoint, null, null, true);
			if(topRight_ != null)
			{
				destPoint.x = smallTopLeft.width;
				thumbnailData.copyPixels(smallTopRight, sourceRect, destPoint, null, null, true);
			}
				
			if(bottomLeft_ != null)
			{
				destPoint.x = 0;
				destPoint.y = smallTopLeft.height;
				thumbnailData.copyPixels(smallBottomLeft, sourceRect, destPoint, null, null, true);
			}
			if(bottomRight_ != null)
			{
				destPoint.x = smallTopLeft.width;
				destPoint.y = smallTopLeft.height;
				thumbnailData.copyPixels(smallBottomRight, sourceRect, destPoint, null, null, true);
			}
				
			return thumbnailData;
		}
	}
}